package com.ponhu.ea2.goodsCenter.provider.facade.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.google.common.collect.Maps;
import com.ponhu.ea2.common.basic.model.PagedResult;
import com.ponhu.ea2.constants.CommonConstant;
import com.ponhu.ea2.constants.DictConstant;
import com.ponhu.ea2.entity.Inventory;
import com.ponhu.ea2.entity.PhBrand;
import com.ponhu.ea2.entity.PhInventoryPropertyValueMd;
import com.ponhu.ea2.entity.PhMaterialPropertyValueMd;
import com.ponhu.ea2.goodsCenter.provider.biz.ESPickInventoryService;
import com.ponhu.ea2.goodsCenter.provider.mapper.*;
import com.ponhu.ea2.goodsCenter.provider.service.InventoryService;
import com.ponhu.ea2.goodsCenter.provider.service.PhBrandService;
import com.ponhu.ea2.goodsCenter.provider.utils.DataConverterUtils;
import com.ponhu.ea2.goodsCenter.provider.utils.ProBeanUtils;
import com.ponhu.ea2.properties.GoodsProperties;
import com.ponhu.ea2.query.PickInventoryQuery;
import com.ponhu.ea2.scmcenter.facade.bms.common.CommonService;
import com.ponhu.ea2.scmcenter.model.vo.common.CommonTypeVo;
import com.ponhu.ea2.service.facade.PickInventoryManageService;
import com.ponhu.ea2.support.exception.BusinessRuntimeException;
import com.ponhu.ea2.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.config.annotation.Method;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.ponhu.ea2.constants.CommonConstant.PICK_INVENTORY_IMPORT_LIMIT;
import static com.ponhu.ea2.enums.ResponseCodeEnum.INVENTORY_EDIT_EXCEPTION_800209;
import static com.ponhu.ea2.enums.ResponseCodeEnum.PICK_INVENTORY_TOO_LONG_800701;

/**
 * @author Wang
 * @date 2021/12/10 5:47 下午
 */
@Slf4j
@DubboService(version = "1.0.0", interfaceClass = PickInventoryManageService.class, timeout = 15000, retries = -1, methods = {
        @Method(name = "getPickExportVoList", timeout = 1800000)
})
public class PickInventoryManageServiceImpl implements PickInventoryManageService {

    @Resource
    GoodsProperties goodsProperties;

    @DubboReference(version = "1.0.0", check = false)
    private CommonService commonService;

    @Autowired
    private InventoryService inventoryService;
    @Autowired
    private InventoryMapper inventoryMapper;
    @Autowired
    private MaterialMapper materialMapper;
    @Autowired
    private PhBrandService brandService;
    @Autowired
    private PhCategoryMapper categoryMapper;
    @Autowired
    private PhInventoryAccessoryMapper inventoryAccessoryMapper;
    @Autowired
    private PhMaterialPropertyValueMdMapper materialPropertyValueMdMapper;
    @Autowired
    private PhInventoryPropertyValueMdMapper inventoryPropertyValueMdMapper;
    @Resource
    private ESPickInventoryService esPickInventoryService;

    @Override
    public PagedResult<PickInventoryVo> getPickInventoryListByCondition(PickInventoryQuery query) {
        //去除String参数左右空格
        trimAndConvertHandler(query);
        //转换分类id，将所有一级，二级转换成三级
        convertCategoryIds(query);

        PagedResult<PickInventoryVo> data = inventoryService.getPickInventoryListByCondition(query);
        List<PickInventoryVo> result = data.getResult();

        setBaseData2(result);
        setPropertyData(result);
        setStockData2(result);
        return data;
    }

    private void convertCategoryIds(PickInventoryQuery query) {
        if (query.getFirstCategoryId() != null) {
            List<PhCategoryLevel3Vo> level3Vos = categoryMapper.getCategoryLevel3VosById(query.getFirstCategoryId(), null, null);
            if (CollectionUtils.isNotEmpty(level3Vos)) {
                query.setCategoryIds(level3Vos.stream().map(PhCategoryLevel3Vo::getLevel3Id).collect(Collectors.toList()));
            }
        }
        if (query.getSecondCategoryId() != null) {
            List<PhCategoryLevel3Vo> level3Vos = categoryMapper.getCategoryLevel3VosById(null, query.getSecondCategoryId(), null);
            if (CollectionUtils.isNotEmpty(level3Vos)) {
                query.setCategoryIds(level3Vos.stream().map(PhCategoryLevel3Vo::getLevel3Id).collect(Collectors.toList()));
            }
        }
    }

    private void setStockData2(List<PickInventoryVo> result) {
        if (CollectionUtils.isEmpty(result))
            return;
        List<Long> inventoryIds = result.stream().map(PickInventoryVo::getInventoryId).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(inventoryIds)) {
            return;
        }

        List<PickInventoryStockVo> inventoryStockVoList = inventoryMapper.getInventoryStockInfo(inventoryIds);
        if (CollectionUtils.isEmpty(inventoryStockVoList)) {
            return;
        }
        Map<Long, PickInventoryStockVo> stockVoMap = inventoryStockVoList.stream().collect(Collectors.toMap(PickInventoryStockVo::getInventoryId, i -> i));

        result.stream().parallel().forEach(pickInventoryVo -> {
            PickInventoryStockVo stockVo = stockVoMap.get(pickInventoryVo.getInventoryId());
            if (stockVo != null) {
                pickInventoryVo.setTotalSalesStockNum(stockVo.getTotalSalesStockNum());
                pickInventoryVo.setTotalRealStockNum(stockVo.getTotalRealStockNum());
                pickInventoryVo.setFreeStockNum(stockVo.getFreeStockNum());
                pickInventoryVo.setWarehousePlace(stockVo.getWarehousePlace());
            }
        });

    }

    private void setPropertyData(List<PickInventoryVo> result) {
        if (CollectionUtils.isEmpty(result)) {
            return;
        }
        //获取附件与配件数据
        Map<Long, List<PhInventoryAccessoryVo>> annexMap = null;
        Map<Long, List<PhInventoryAccessoryVo>> accessoryMap = null;
        List<Long> inventoryIds = result.stream().map(PickInventoryVo::getInventoryId).collect(Collectors.toList());

        List<PhInventoryAccessoryVo> accessoryVoList = inventoryAccessoryMapper.getInventoryAccessoryByIds(inventoryIds);

        if (CollectionUtils.isNotEmpty(accessoryVoList)) {
            List<PhInventoryAccessoryVo> annxList = accessoryVoList.stream().parallel().filter(f -> f.getDictType().equals(DictConstant.INVENTORY_ANNEX)).collect(Collectors.toList());
            List<PhInventoryAccessoryVo> accessoryList = accessoryVoList.stream().parallel().filter(f -> f.getDictType().equals(DictConstant.INVENTORY_ACCESSORY)).collect(Collectors.toList());

            if (CollectionUtils.isNotEmpty(annxList)) {
                annexMap = annxList.stream().collect(Collectors.groupingBy(PhInventoryAccessoryVo::getInventoryId));
            }
            if (CollectionUtils.isNotEmpty(accessoryList)) {
                accessoryMap = accessoryList.stream().collect(Collectors.groupingBy(PhInventoryAccessoryVo::getInventoryId));
            }
        }

        if (annexMap == null && accessoryMap == null) {
            return;
        }

        Map<Long, List<PhInventoryAccessoryVo>> finalAnnexMap = annexMap;
        Map<Long, List<PhInventoryAccessoryVo>> finalAccessoryMap = accessoryMap;
        result.stream().parallel().forEach(pickInventoryVo -> {
            if (finalAnnexMap != null) {
                List<PhInventoryAccessoryVo> list = finalAnnexMap.get(pickInventoryVo.getInventoryId());
                if (CollectionUtils.isNotEmpty(list)) {
                    List<String> collect = list.stream().map(PhInventoryAccessoryVo::getDictItemLabel).collect(Collectors.toList());
                    pickInventoryVo.setAnnexStringList(collect);
                }

            }
            if (finalAccessoryMap != null) {
                List<PhInventoryAccessoryVo> list = finalAccessoryMap.get(pickInventoryVo.getInventoryId());
                if (CollectionUtils.isNotEmpty(list)) {
                    List<String> collect = list.stream().map(PhInventoryAccessoryVo::getDictItemLabel).collect(Collectors.toList());
                    pickInventoryVo.setAccessoryStringList(collect);
                }

            }
        });

        //获取属性数据
        List<Long> categoryIds = result.stream().parallel().map(PickInventoryVo::getCategoryId).distinct().collect(Collectors.toList());

        List<PhCategoryLevel3Vo> categoryList = categoryMapper.getCategoryLevel3VosByIds(categoryIds);
        Map<Long, PhCategoryLevel3Vo> categoryMap = categoryList.stream().collect(Collectors.toMap(PhCategoryLevel3Vo::getLevel3Id, i -> i));

        List<PhInventoryPropertyValueMd> inventoryPropertyList = inventoryPropertyValueMdMapper.getInventoryPropertyValueListByInventoryIds(inventoryIds);
        Map<Long, List<PhInventoryPropertyValueMd>> iMap = inventoryPropertyList.stream().collect(Collectors.groupingBy(PhInventoryPropertyValueMd::getInventoryId));

        List<Long> materialIds = result.stream().map(PickInventoryVo::getMaterialId).collect(Collectors.toList());
        Map<Long, List<PhMaterialPropertyValueMd>> mMap = null;
        if (CollectionUtils.isNotEmpty(materialIds)) {
            List<PhMaterialPropertyValueMd> materialPropertyList = materialPropertyValueMdMapper.getMaterialPropertyValueListByMaterialIds(materialIds);

            mMap = materialPropertyList.stream().parallel().collect(Collectors.groupingBy(PhMaterialPropertyValueMd::getMaterialId));
        }

        convertPropertyData(result, categoryMap, iMap, mMap);
    }

    private void convertPropertyData(List<PickInventoryVo> result, Map<Long, PhCategoryLevel3Vo> categoryMap, Map<Long, List<PhInventoryPropertyValueMd>> iMap, Map<Long, List<PhMaterialPropertyValueMd>> mMap) {
        result.stream().parallel().forEach(pickInventoryVo -> {
            PhCategoryLevel3Vo categoryLevel3Vo = categoryMap.get(pickInventoryVo.getCategoryId());
            if (categoryLevel3Vo != null) {
                switch (categoryLevel3Vo.getLevel1name()) {
                    case "箱包":
                        if (CollectionUtils.isNotEmpty(mMap)) {
                            List<PhMaterialPropertyValueMd> valueMdList = mMap.get(pickInventoryVo.getMaterialId());
                            if (CollectionUtils.isNotEmpty(valueMdList)) {
                                List<PhPropertyVo> collect = valueMdList.stream().filter(f -> (f.getPropertyName().equals("尺码") ||
                                        f.getPropertyName().equals("外表材质") ||
                                        f.getPropertyName().equals("外表颜色") ||
                                        f.getPropertyName().equals("内衬颜色") ||
                                        f.getPropertyName().equals("五金颜色"))).map(i -> new PhPropertyVo().setPropertyName(i.getPropertyName())
                                        .setPropertyValue(i.getPropertyValue())).collect(Collectors.toList());
                                pickInventoryVo.setPropertyVoList(collect);
                            }
                        }
                        if (CollectionUtils.isNotEmpty(iMap)) {
                            List<PhInventoryPropertyValueMd> valueMdList = iMap.get(pickInventoryVo.getInventoryId());
                            if (CollectionUtils.isNotEmpty(valueMdList)) {
                                List<PhPropertyVo> collect = valueMdList.stream().filter(f -> (f.getPropertyName().equals("尺码") ||
                                        f.getPropertyName().equals("外表材质") ||
                                        f.getPropertyName().equals("外表颜色") ||
                                        f.getPropertyName().equals("内衬颜色") ||
                                        f.getPropertyName().equals("五金颜色"))).map(i -> new PhPropertyVo().setPropertyName(i.getPropertyName())
                                        .setPropertyValue(i.getPropertyValue())).collect(Collectors.toList());

                                if (CollectionUtils.isNotEmpty(collect)) {
                                    if (CollectionUtils.isEmpty(pickInventoryVo.getPropertyVoList())) {
                                        pickInventoryVo.setPropertyVoList(collect);
                                    } else {
                                        pickInventoryVo.getPropertyVoList().addAll(collect);
                                        pickInventoryVo.setPropertyVoList(pickInventoryVo.getPropertyVoList());
                                    }
                                }
                            }
                        }
                        break;
                    case "腕表":
                        if (CollectionUtils.isNotEmpty(mMap)) {
                            List<PhMaterialPropertyValueMd> valueMdList = mMap.get(pickInventoryVo.getMaterialId());
                            if (CollectionUtils.isNotEmpty(valueMdList)) {
                                List<PhPropertyVo> collect = valueMdList.stream().filter(f -> (
                                        f.getPropertyName().equals("表壳材质") ||
                                                f.getPropertyName().equals("外表颜色") ||
                                                f.getPropertyName().equals("机芯类型") ||
                                                f.getPropertyName().equals("表扣类型") ||
                                                f.getPropertyName().equals("腕围") ||
                                                f.getPropertyName().equals("表径"))).map(i -> new PhPropertyVo().setPropertyName(i.getPropertyName())
                                        .setPropertyValue(i.getPropertyValue())).collect(Collectors.toList());
                                pickInventoryVo.setPropertyVoList(collect);
                            }
                        }
                        if (CollectionUtils.isNotEmpty(iMap)) {
                            List<PhInventoryPropertyValueMd> valueMdList = iMap.get(pickInventoryVo.getInventoryId());
                            if (CollectionUtils.isNotEmpty(valueMdList)) {
                                List<PhPropertyVo> collect = valueMdList.stream().filter(f -> (
                                        f.getPropertyName().equals("表壳材质") ||
                                                f.getPropertyName().equals("外表颜色") ||
                                                f.getPropertyName().equals("机芯类型") ||
                                                f.getPropertyName().equals("表扣类型") ||
                                                f.getPropertyName().equals("腕围") ||
                                                f.getPropertyName().equals("表径"))).map(i -> new PhPropertyVo().setPropertyName(i.getPropertyName())
                                        .setPropertyValue(i.getPropertyValue())).collect(Collectors.toList());

                                if (CollectionUtils.isNotEmpty(pickInventoryVo.getPropertyVoList())) {
                                    pickInventoryVo.setPropertyVoList(collect);
                                } else {
                                    pickInventoryVo.getPropertyVoList().addAll(collect);
                                    pickInventoryVo.setPropertyVoList(pickInventoryVo.getPropertyVoList());
                                }
                            }
                        }
                        break;
                    case "饰品":
                        if (CollectionUtils.isNotEmpty(mMap)) {
                            List<PhMaterialPropertyValueMd> valueMdList = mMap.get(pickInventoryVo.getMaterialId());
                            if (CollectionUtils.isNotEmpty(valueMdList)) {
                                List<PhPropertyVo> collect = valueMdList.stream().filter(f -> (
                                        f.getPropertyName().equals("颜色") ||
                                                f.getPropertyName().equals("材质") ||
                                                f.getPropertyName().equals("链材质") ||
                                                f.getPropertyName().equals("镶嵌材质") ||
                                                f.getPropertyName().equals("链长") ||
                                                f.getPropertyName().equals("克重"))).map(i -> new PhPropertyVo().setPropertyName(i.getPropertyName())
                                        .setPropertyValue(i.getPropertyValue())).collect(Collectors.toList());
                                pickInventoryVo.setPropertyVoList(collect);
                            }
                        }
                        if (CollectionUtils.isNotEmpty(iMap)) {
                            List<PhInventoryPropertyValueMd> valueMdList = iMap.get(pickInventoryVo.getInventoryId());
                            if (CollectionUtils.isNotEmpty(valueMdList)) {
                                List<PhPropertyVo> collect = valueMdList.stream().filter(f -> (
                                        f.getPropertyName().equals("颜色") ||
                                                f.getPropertyName().equals("材质") ||
                                                f.getPropertyName().equals("链材质") ||
                                                f.getPropertyName().equals("镶嵌材质") ||
                                                f.getPropertyName().equals("链长") ||
                                                f.getPropertyName().equals("克重"))).map(i -> new PhPropertyVo().setPropertyName(i.getPropertyName())
                                        .setPropertyValue(i.getPropertyValue())).collect(Collectors.toList());

                                if (CollectionUtils.isNotEmpty(pickInventoryVo.getPropertyVoList())) {
                                    pickInventoryVo.setPropertyVoList(collect);
                                } else {
                                    pickInventoryVo.getPropertyVoList().addAll(collect);
                                    pickInventoryVo.setPropertyVoList(pickInventoryVo.getPropertyVoList());
                                }
                            }
                        }
                        break;
                    case "潮玩":
                        if (CollectionUtils.isNotEmpty(mMap)) {
                            List<PhMaterialPropertyValueMd> valueMdList = mMap.get(pickInventoryVo.getMaterialId());
                            if (CollectionUtils.isNotEmpty(valueMdList)) {
                                List<PhPropertyVo> collect = valueMdList.stream().filter(f -> (
                                        f.getPropertyName().equals("颜色") ||
                                                f.getPropertyName().equals("材质"))).map(i -> new PhPropertyVo().setPropertyName(i.getPropertyName())
                                        .setPropertyValue(i.getPropertyValue())).collect(Collectors.toList());
                                pickInventoryVo.setPropertyVoList(collect);
                            }
                        }
                        if (CollectionUtils.isNotEmpty(iMap)) {
                            List<PhInventoryPropertyValueMd> valueMdList = iMap.get(pickInventoryVo.getInventoryId());
                            if (CollectionUtils.isNotEmpty(valueMdList)) {
                                List<PhPropertyVo> collect = valueMdList.stream().filter(f -> (
                                        f.getPropertyName().equals("颜色") ||
                                                f.getPropertyName().equals("材质"))).map(i -> new PhPropertyVo().setPropertyName(i.getPropertyName())
                                        .setPropertyValue(i.getPropertyValue())).collect(Collectors.toList());

                                if (CollectionUtils.isNotEmpty(pickInventoryVo.getPropertyVoList())) {
                                    pickInventoryVo.setPropertyVoList(collect);
                                } else {
                                    pickInventoryVo.getPropertyVoList().addAll(collect);
                                    pickInventoryVo.setPropertyVoList(pickInventoryVo.getPropertyVoList());
                                }
                            }
                        }
                        break;
                    case "服饰":
                    case "鞋履":
                        if (CollectionUtils.isNotEmpty(mMap)) {
                            List<PhMaterialPropertyValueMd> valueMdList = mMap.get(pickInventoryVo.getMaterialId());
                            if (CollectionUtils.isNotEmpty(valueMdList)) {
                                List<PhPropertyVo> collect = valueMdList.stream().filter(f -> (f.getPropertyName().equals("尺码") ||
                                        f.getPropertyName().equals("颜色") ||
                                        f.getPropertyName().equals("材质"))).map(i -> new PhPropertyVo().setPropertyName(i.getPropertyName())
                                        .setPropertyValue(i.getPropertyValue())).collect(Collectors.toList());
                                pickInventoryVo.setPropertyVoList(collect);
                            }
                        }
                        if (CollectionUtils.isNotEmpty(iMap)) {
                            List<PhInventoryPropertyValueMd> valueMdList = iMap.get(pickInventoryVo.getInventoryId());
                            if (CollectionUtils.isNotEmpty(valueMdList)) {
                                List<PhPropertyVo> collect = valueMdList.stream().filter(f -> (f.getPropertyName().equals("尺码") ||
                                        f.getPropertyName().equals("颜色") ||
                                        f.getPropertyName().equals("材质"))).map(i -> new PhPropertyVo().setPropertyName(i.getPropertyName())
                                        .setPropertyValue(i.getPropertyValue())).collect(Collectors.toList());

                                if (CollectionUtils.isNotEmpty(pickInventoryVo.getPropertyVoList())) {
                                    pickInventoryVo.setPropertyVoList(collect);
                                } else {
                                    pickInventoryVo.getPropertyVoList().addAll(collect);
                                    pickInventoryVo.setPropertyVoList(pickInventoryVo.getPropertyVoList());
                                }
                            }
                        }
                        break;
                    case "美妆":
                        if (CollectionUtils.isNotEmpty(mMap)) {
                            List<PhMaterialPropertyValueMd> valueMdList = mMap.get(pickInventoryVo.getMaterialId());
                            if (CollectionUtils.isNotEmpty(valueMdList)) {
                                List<PhPropertyVo> collect = valueMdList.stream().filter(f -> (f.getPropertyName().equals("规格") ||
                                        f.getPropertyName().equals("瓶体材质") ||
                                        f.getPropertyName().equals("适用性别") ||
                                        f.getPropertyName().equals("香调") ||
                                        f.getPropertyName().equals("适用人群") ||
                                        f.getPropertyName().equals("适用肤质") ||
                                        f.getPropertyName().equals("产品功效"))).map(i -> new PhPropertyVo().setPropertyName(i.getPropertyName())
                                        .setPropertyValue(i.getPropertyValue())).collect(Collectors.toList());
                                pickInventoryVo.setPropertyVoList(collect);
                            }
                        }
                        if (CollectionUtils.isNotEmpty(iMap)) {
                            List<PhInventoryPropertyValueMd> valueMdList = iMap.get(pickInventoryVo.getInventoryId());
                            if (CollectionUtils.isNotEmpty(valueMdList)) {
                                List<PhPropertyVo> collect = valueMdList.stream().filter(f -> (f.getPropertyName().equals("规格") ||
                                        f.getPropertyName().equals("瓶体材质") ||
                                        f.getPropertyName().equals("适用性别") ||
                                        f.getPropertyName().equals("香调") ||
                                        f.getPropertyName().equals("适用人群") ||
                                        f.getPropertyName().equals("适用肤质") ||
                                        f.getPropertyName().equals("产品功效"))).map(i -> new PhPropertyVo().setPropertyName(i.getPropertyName())
                                        .setPropertyValue(i.getPropertyValue())).collect(Collectors.toList());

                                if (CollectionUtils.isNotEmpty(pickInventoryVo.getPropertyVoList())) {
                                    pickInventoryVo.setPropertyVoList(collect);
                                } else {
                                    pickInventoryVo.getPropertyVoList().addAll(collect);
                                    pickInventoryVo.setPropertyVoList(pickInventoryVo.getPropertyVoList());
                                }
                            }
                        }
                        break;
                }
            }

        });
    }

    /**
     * 根据条件查询导出的选品详细数据（限制3000条）
     *
     * @param query
     * @return
     */
    @Override
    public List<PickInventoryDetailVo> exportPickInventoryDataList(PickInventoryQuery query) {
        //去除String参数左右空格
        trimAndConvertHandler(query);
        //转换分类id，将所有一级，二级转换成三级
        convertCategoryIds(query);
        List<PickInventoryDetailVo> detailVoList = inventoryService.getImportPickInventoryDataList(query);

        if (CollectionUtils.isNotEmpty(detailVoList) && detailVoList.size() > PICK_INVENTORY_IMPORT_LIMIT) {
            throw new BusinessRuntimeException(PICK_INVENTORY_TOO_LONG_800701);
        }

        //组装基本数据
        setBaseData(detailVoList);
        //组装物料数据
        setMaterialData(detailVoList);

        //组装货品属性数据
        setInventoryPropertyData(detailVoList);

        //组装库存数据
        setStockData(detailVoList);

        //组装采购数据(二奢)
        setPurchaseData(detailVoList);

        return detailVoList;
    }

    private void setStockData(List<PickInventoryDetailVo> detailVoList) {
        if (CollectionUtils.isEmpty(detailVoList))
            return;
        List<Long> inventoryIds = detailVoList.stream().map(PickInventoryVo::getInventoryId).collect(Collectors.toList());

        if (CollectionUtils.isNotEmpty(inventoryIds)) {
            List<PickInventoryStockVo> inventoryBaseStockVoList = inventoryMapper.getInventoryStockInfo(inventoryIds);
            if (CollectionUtils.isNotEmpty(inventoryBaseStockVoList)) {
                Map<Long, PickInventoryStockVo> stockVoMap = inventoryBaseStockVoList.stream().collect(Collectors.toMap(PickInventoryStockVo::getInventoryId, i -> i));

                detailVoList.stream().parallel().forEach(pickInventoryVo -> {
                    PickInventoryStockVo stockVo = stockVoMap.get(pickInventoryVo.getInventoryId());
                    if (stockVo != null) {
                        pickInventoryVo.setTotalSalesStockNum(stockVo.getTotalSalesStockNum());
                        pickInventoryVo.setTotalRealStockNum(stockVo.getTotalRealStockNum());
                        pickInventoryVo.setFreeStockNum(stockVo.getFreeStockNum());
                        String warehousePlace = stockVo.getWarehousePlace();
                        pickInventoryVo.setWarehousePlace(warehousePlace);
                    }
                });
            }
        }

        List<Long> secondhandInventoryIds = detailVoList.stream().parallel()
                .filter(f -> CommonConstant.YES_OR_NO.YES == f.getIsSecondhand())
                .map(PickInventoryVo::getInventoryId).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(secondhandInventoryIds)) {
            return;
        }

        List<PickInventoryStockVo> inventoryStockVoList = inventoryMapper.getInventoryWarehouseAliveDay(secondhandInventoryIds);
        if (CollectionUtils.isEmpty(inventoryStockVoList)) {
            return;
        }
        Map<Long, PickInventoryStockVo> stockVoMap = inventoryStockVoList.stream().collect(Collectors.toMap(PickInventoryStockVo::getInventoryId, i -> i));

        detailVoList.stream().parallel().forEach(detailVo -> {
            PickInventoryStockVo stockVo = stockVoMap.get(detailVo.getInventoryId());
            if (stockVo != null && stockVo.getFirstWarehouseTime() != null) {
                detailVo.setWarehouseAliveDay(
                        DataConverterUtils.calcDayOfTwoDatetime(stockVo.getFirstWarehouseTime(), stockVo.getLastWarehouseTime()));
            }
        });

    }

    private void setPurchaseData(List<PickInventoryDetailVo> detailVoList) {
        List<String> secondhandInventoryCodeList = detailVoList.stream().parallel()
                .filter(f -> CommonConstant.YES_OR_NO.YES == f.getIsSecondhand())
                .map(PickInventoryVo::getInventoryCode).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(secondhandInventoryCodeList)) {
            return;
        }

        List<PickInventoryPurchaseVo> purchaseVoList = inventoryMapper.getInventoryPurchaseInfo(secondhandInventoryCodeList);

        if (CollectionUtils.isNotEmpty(purchaseVoList)) {
            Map<Integer, String> whTypeMap = commonService.wareHouseTypeList().stream()
                    .collect(Collectors.toMap(CommonTypeVo::getId, CommonTypeVo::getValue, (v1, v2) -> v2));
//            Map<Integer, String> whTypeMap = Maps.newHashMap();

            Map<String, PickInventoryPurchaseVo> purchaseMap = purchaseVoList.stream()
                    .map(vo -> vo.setWarehouseTypeName(whTypeMap.get(vo.getWarehouseType())))
                    .collect(Collectors.toMap(PickInventoryPurchaseVo::getInventoryCode, Function.identity()));

            detailVoList.stream().parallel().forEach(detailVo -> {
                detailVo.setPickInventoryPurchaseVo(purchaseMap.get(detailVo.getInventoryCode()));
            });
        }

    }

    private void setBaseData2(List<PickInventoryVo> pickInventoryVoList) {
        if (CollectionUtils.isEmpty(pickInventoryVoList)) {
            return;
        }

        Map<Long, PhBrand> brandNameMap = null;
        Map<Long, String> categoryNameMap = null;

        //获取品牌名称
        Set<Long> brandIds = pickInventoryVoList.stream().parallel().map(PickInventoryVo::getBrandId).collect(Collectors.toSet());
        if (CollectionUtils.isNotEmpty(brandIds)) {
            List<PhBrand> brandList = brandService.listByIds(brandIds);
            brandNameMap = brandList.stream().parallel().collect(Collectors.toMap(PhBrand::getId, i -> i));
        }

        //获取品类名称
        List<Long> categoryIds = pickInventoryVoList.stream().parallel().map(PickInventoryVo::getCategoryId).distinct().collect(Collectors.toList());

        if (CollectionUtils.isNotEmpty(categoryIds)) {
            List<PhCategoryLevel3Vo> categoryList = categoryMapper.getCategoryLevel3VosByIds(categoryIds);
            categoryNameMap = categoryList.stream().parallel().collect(Collectors.toMap(PhCategoryLevel3Vo::getLevel3Id, i -> String.format("%s-%s-%s", i.getLevel1name(), i.getLevel2name(), i.getLevel3name())));
        }

        Map<Long, PhBrand> finalBrandNameMap = brandNameMap;
        Map<Long, String> finalCategoryNameMap = categoryNameMap;
        pickInventoryVoList.stream().parallel().forEach(detailVo -> {
            if (finalBrandNameMap != null) {
                detailVo.setBrandCnName(finalBrandNameMap.get(detailVo.getBrandId()) == null ? null : finalBrandNameMap.get(detailVo.getBrandId()).getCnName());
                detailVo.setBrandEnName(finalBrandNameMap.get(detailVo.getBrandId()) == null ? null : finalBrandNameMap.get(detailVo.getBrandId()).getEnName());
            }
            if (finalCategoryNameMap != null) {
                detailVo.setCategoryName(finalCategoryNameMap.get(detailVo.getCategoryId()));
            }

        });
    }

    private void setBaseData(List<PickInventoryDetailVo> detailVoList) {
        if (CollectionUtils.isEmpty(detailVoList)) {
            return;
        }

        Map<Long, PhBrand> brandNameMap = null;
        Map<Long, String> categoryNameMap = null;
        Map<Long, List<PhInventoryAccessoryVo>> annxMap = null;
        Map<Long, List<PhInventoryAccessoryVo>> accessoryMap = null;

        //获取品牌名称
        Set<Long> brandIds = detailVoList.stream().parallel().map(PickInventoryDetailVo::getBrandId).collect(Collectors.toSet());
        if (CollectionUtils.isNotEmpty(brandIds)) {
            List<PhBrand> brandList = brandService.listByIds(brandIds);
            brandNameMap = brandList.stream().parallel().collect(Collectors.toMap(PhBrand::getId, i -> i));
        }

        //获取品类名称
        List<Long> categoryIds = detailVoList.stream().parallel().map(PickInventoryDetailVo::getCategoryId).distinct().collect(Collectors.toList());

        if (CollectionUtils.isNotEmpty(categoryIds)) {
            List<PhCategoryLevel3Vo> categoryList = categoryMapper.getCategoryLevel3VosByIds(categoryIds);
            categoryNameMap = categoryList.stream().parallel().collect(Collectors.toMap(PhCategoryLevel3Vo::getLevel3Id, i -> String.format("%s-%s-%s", i.getLevel1name(), i.getLevel2name(), i.getLevel3name())));
        }

        //获取附件与配件
        List<Long> inventoryIds = detailVoList.stream().map(PickInventoryVo::getInventoryId).collect(Collectors.toList());

        List<PhInventoryAccessoryVo> accessoryVoList = inventoryAccessoryMapper.getInventoryAccessoryByIds(inventoryIds);

        if (CollectionUtils.isNotEmpty(accessoryVoList)) {
            List<PhInventoryAccessoryVo> annxList = accessoryVoList.stream().parallel().filter(f -> f.getDictType().equals(DictConstant.INVENTORY_ANNEX)).collect(Collectors.toList());
            List<PhInventoryAccessoryVo> accessoryList = accessoryVoList.stream().parallel().filter(f -> f.getDictType().equals(DictConstant.INVENTORY_ACCESSORY)).collect(Collectors.toList());

            if (CollectionUtils.isNotEmpty(annxList)) {
                annxMap = annxList.stream().collect(Collectors.groupingBy(PhInventoryAccessoryVo::getInventoryId));
            }
            if (CollectionUtils.isNotEmpty(accessoryList)) {
                accessoryMap = accessoryList.stream().collect(Collectors.groupingBy(PhInventoryAccessoryVo::getInventoryId));
            }
        }

        Map<Long, PhBrand> finalBrandNameMap = brandNameMap;
        Map<Long, String> finalCategoryNameMap = categoryNameMap;
        Map<Long, List<PhInventoryAccessoryVo>> finalAnnxMap = annxMap;
        Map<Long, List<PhInventoryAccessoryVo>> finalAccessoryMap = accessoryMap;
        detailVoList.stream().parallel().forEach(detailVo -> {
            if (finalBrandNameMap != null) {
                detailVo.setBrandCnName(finalBrandNameMap.get(detailVo.getBrandId()) == null ? null : finalBrandNameMap.get(detailVo.getBrandId()).getCnName());
                detailVo.setBrandEnName(finalBrandNameMap.get(detailVo.getBrandId()) == null ? null : finalBrandNameMap.get(detailVo.getBrandId()).getEnName());
            }
            if (finalCategoryNameMap != null) {
                detailVo.setCategoryName(finalCategoryNameMap.get(detailVo.getCategoryId()));
            }
            if (finalAnnxMap != null) {
                detailVo.setAnnexList(finalAnnxMap.get(detailVo.getInventoryId()));
            }
            if (finalAccessoryMap != null) {
                detailVo.setAccessoryList(finalAccessoryMap.get(detailVo.getInventoryId()));
            }
        });
    }

    private void setInventoryPropertyData(List<PickInventoryDetailVo> detailVoList) {
        if (CollectionUtils.isEmpty(detailVoList)) {
            return;
        }
        List<Long> inventoryIds = detailVoList.stream().parallel().map(PickInventoryVo::getInventoryId).collect(Collectors.toList());
        List<PhInventoryPropertyValueMd> propertyValueMdList = inventoryPropertyValueMdMapper.getInventoryPropertyValueListByInventoryIds(inventoryIds);
        if (CollectionUtils.isNotEmpty(propertyValueMdList)) {
            detailVoList.stream().parallel().forEach(detailVo -> {
                //查找自己的货品属性
                List<PhPropertyVo> propertyVoList = propertyValueMdList.stream().parallel().filter(f -> f.getInventoryId().equals(detailVo.getInventoryId()))
                        .map(i -> ProBeanUtils.copyProperties(i, PhPropertyVo.class)).collect(Collectors.toList());
                detailVo.setPhPropertList(propertyVoList);
            });
        }
    }

    private void setMaterialData(List<PickInventoryDetailVo> detailVoList) {
        //找到物料ID不为空的数据
        List<Long> materialIds = detailVoList.stream().parallel().filter(i -> i.getMaterialId() != null).collect(Collectors.toList())
                .stream().parallel().map(PickInventoryVo::getMaterialId).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(materialIds)) {
            return;
        }

        //获取物料数据
        List<PhMaterialVo> materialVoList = materialMapper.getMaterialVoByIds(materialIds);

        if (CollectionUtils.isEmpty(materialVoList)) {
            return;
        }

        //获取物料属性数据7·
        List<PhMaterialPropertyValueMd> propertyValueMdList = materialPropertyValueMdMapper.getMaterialPropertyValueListByMaterialIds(materialIds);

        //组装物料数据
        detailVoList.stream().parallel().forEach(detailVo -> materialVoList.stream().filter(f -> f.getMaterialId().equals(detailVo.getMaterialId())).findFirst().ifPresent(
                (materialVo) -> {
                    if (CollectionUtils.isNotEmpty(propertyValueMdList)) {
                        List<PhPropertyVo> propertyVoList = propertyValueMdList.stream()
                                .filter(f -> f.getMaterialId().equals(detailVo.getMaterialId()))
                                .map(i -> ProBeanUtils.copyProperties(i, PhPropertyVo.class))
                                .collect(Collectors.toList());

                        materialVo.setMaterialPropertyValueList(propertyVoList);
                    }
                    detailVo.setPhMaterialVo(materialVo);
                }));
    }

    @Override
    public PickInventoryDetailVo getPickInventoryByInventoryId(Long inventoryId) {
        return getPickInventoryDetail(inventoryId, CommonConstant.YES_OR_NO.YES_STR);

    }

    private PickInventoryDetailVo getPickInventoryDetail(Long inventoryId, String pickInventoryRule) {
        Inventory inventory = inventoryService.getById(inventoryId);
        if (inventory == null) {
            throw new BusinessRuntimeException(INVENTORY_EDIT_EXCEPTION_800209);
        }
        List<PickInventoryDetailVo> pickInventoryDetailVos = exportPickInventoryDataList(
                new PickInventoryQuery().setInventoryId(inventoryId).setPickInventoryRule(pickInventoryRule));
        if (CollectionUtils.isNotEmpty(pickInventoryDetailVos)) {
            return pickInventoryDetailVos.get(0);
        } else {
            throw new BusinessRuntimeException(INVENTORY_EDIT_EXCEPTION_800209);
        }
    }

    /**
     * 根据货品ID查询选品详情：FromMysql
     *
     * @param inventoryId
     * @param pickInventoryRule
     * @return
     */
    @Override
    public PickInventoryDetailVo getPickInventoryByInventoryId(Long inventoryId, String pickInventoryRule) {
        return getPickInventoryDetail(inventoryId, pickInventoryRule);
    }

    /**
     * 选品列表导出
     *
     * @param query
     * @param tClass
     * @param <T>
     * @return
     */
    @Override
    public <T extends PickExportVo> List<PickExportVo> getPickExportVoList(PickInventoryQuery query, Class<T> tClass) {

        long start = System.currentTimeMillis();
        List<PickInventoryDetailVo> pickInventoryDetailVos;
        if (goodsProperties.getUseEsForPickInventory()) {
            log.info("选品数据导出-ES");
            pickInventoryDetailVos = exportPickInventoryDataListFromEs(query);
        } else {
            log.info("选品数据导出-mysql");
            pickInventoryDetailVos = exportPickInventoryDataList(query);
        }
//        System.out.printf("\033[32m importPickInventoryDataList ===>> %s ms \033[0m\n", System.currentTimeMillis() - start);

        return pickInventoryDetailVos.parallelStream().map(detail -> {

            T t = ProBeanUtils.copyProperties(detail, tClass);

            // 导出货品编码
            if (t instanceof PickCodeExportVo) return t;

            PickInventoryExportVo pickInventoryExportVo = (PickInventoryExportVo) t;

            PhMaterialVo phMaterialVo = detail.getPhMaterialVo();
            if (ObjectUtils.isNotEmpty(phMaterialVo)) {
                BeanUtils.copyProperties(phMaterialVo, pickInventoryExportVo);
                BeanUtils.copyProperties(detail, pickInventoryExportVo);
            }

            // 设置三级分类名称
            pickInventoryExportVo.setCategoryName(detail.getCategoryName());
            // 设置品牌名称
            String brandName = String.format("%s-%s", detail.getBrandEnName(), detail.getBrandCnName());
            pickInventoryExportVo.setBrandName(brandName);

            if (ObjectUtils.isNotEmpty(detail.getPickInventoryPurchaseVo()))
                BeanUtils.copyProperties(detail.getPickInventoryPurchaseVo(), pickInventoryExportVo);

            if (CollectionUtils.isNotEmpty(detail.getAnnexList()))
                pickInventoryExportVo.setAnnexStr(detail.getAnnexList().stream()
                        .map(PhInventoryAccessoryVo::getDictItemLabel).collect(Collectors.joining(", ")));
            if (CollectionUtils.isNotEmpty(detail.getAccessoryList()))
                pickInventoryExportVo.setAccessoryStr(detail.getAccessoryList().stream()
                        .map(PhInventoryAccessoryVo::getDictItemLabel).collect(Collectors.joining(", ")));

            if (CollectionUtils.isNotEmpty(detail.getPhPropertList())) {
                String propsStr = detail.getPhPropertList().stream()
                        .map(prop -> String.format("%s：%s", prop.getPropertyName(), prop.getPropertyValue()))
                        .collect(Collectors.joining("  |  "));
                pickInventoryExportVo.setPropsStr(propsStr);
            }
            if (ObjectUtils.isNotEmpty(phMaterialVo)) {
                if (CollectionUtils.isNotEmpty(phMaterialVo.getMaterialPropertyValueList())) {
                    String propsStr = phMaterialVo.getMaterialPropertyValueList().stream()
                            .map(prop -> String.format("%s：%s", prop.getPropertyName(), prop.getPropertyValue()))
                            .collect(Collectors.joining("  |  "));
                    if (StringUtils.isEmpty(pickInventoryExportVo.getPropsStr())) {
                        pickInventoryExportVo.setPropsStr(propsStr);
                    } else {
                        pickInventoryExportVo.setPropsStr(pickInventoryExportVo.getPropsStr() + "  |  " + propsStr);
                    }
                }
            }

            return pickInventoryExportVo;
        }).collect(Collectors.toList());
    }

    /**
     * 选品列表汇总结果查询
     *
     * @param query
     * @return
     */
    @Override
    public PickInventoryStatisticsVo getPickInventoryStatisticsInfo(PickInventoryQuery query) {
        //去除String参数左右空格
        trimAndConvertHandler(query);
        //转换分类id，将所有一级，二级转换成三级
        convertCategoryIds(query);

        PickInventoryStatisticsVo pickInventoryStatisticsVo = inventoryService.getPickInventoryStatisticsInfo(query);
        return pickInventoryStatisticsVo;
    }

    @Override
    public PagedResult<PickInventoryVo> getPickInventoryListFromES(PickInventoryQuery query) throws IOException {
        //去除String参数左右空格
        trimAndConvertHandler(query);
        //转换分类id，将所有一级，二级转换成三级
        convertCategoryIds(query);
        return esPickInventoryService.getPickInventoryListFromES(query);
    }

    @Override
    public PickInventoryStatisticsVo getPickInventoryStatisticsInfoFromES(PickInventoryQuery query) {
        //去除String参数左右空格
        trimAndConvertHandler(query);
        //转换分类id，将所有一级，二级转换成三级
        convertCategoryIds(query);
        return esPickInventoryService.getPickInventoryStatisticsInfoFromES(query);
    }

    /**
     * 根据货品ID查询选品详情：FromES
     *
     * @param inventoryId
     * @param pickInventoryRule
     * @return
     */
    @Override
    public PickInventoryDetailVo getPickInventoryByInventoryIdFromES(Long inventoryId, String pickInventoryRule) {
        if (inventoryId == null) {
            throw new BusinessRuntimeException(INVENTORY_EDIT_EXCEPTION_800209);
        }

        List<PickInventoryDetailVo> pickInventoryDetailVos = esPickInventoryService.exportPickInventoryDataList(
                new PickInventoryQuery().setInventoryId(inventoryId).setPickInventoryRule(pickInventoryRule));
        if (CollectionUtils.isNotEmpty(pickInventoryDetailVos)) {
            return pickInventoryDetailVos.get(0);
        } else {
            throw new BusinessRuntimeException(INVENTORY_EDIT_EXCEPTION_800209);
        }
    }

    /**
     * 选品查询列表(用于详情和导出)：FromES
     *
     * @param query
     * @return
     */
    @Override
    public List<PickInventoryDetailVo> exportPickInventoryDataListFromEs(PickInventoryQuery query) {
        //去除String参数左右空格
        trimAndConvertHandler(query);
        //转换分类id，将所有一级，二级转换成三级
        convertCategoryIds(query);
        List<PickInventoryDetailVo> detailVoList = esPickInventoryService.exportPickInventoryDataList(query);

        if (CollectionUtils.isNotEmpty(detailVoList) && detailVoList.size() > PICK_INVENTORY_IMPORT_LIMIT) {
            throw new BusinessRuntimeException(PICK_INVENTORY_TOO_LONG_800701);
        }

        return detailVoList;
    }

}
